//多态

class Animal{
    String name;
    int age;
    String color;

    //想对 父类 初始化
    //利用构造方法

//    static {
//        System.out.println("fu类静态代码块");
//    }
//
//    {
//        System.out.println("fu类实例代码块");
//    }
//
//    public static void Me(){
//        System.out.println("fu类静态方法");
//    }
//
//    public void Me2(){
//        System.out.println("fu类方法");
//    }

    public Animal(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
        System.out.println("fu类构造方法");
    }
    //既然父类 有了构造方法  那么也要给子类定义构造方法

    public void eat(){
        System.out.println(this.name + "正在吃");
    }
}

class Dog extends Animal{

    //实例代码块
    //在类之中，方法之外

    //普通代码块
    //在方法之中


//    static {
//        System.out.println("子类静态代码块");
//    }
//
//    {
//        System.out.println("子类实例代码块");
//    }
//
//    public static void me(){
//        System.out.println("子类静态方法");
//    }
//
//    public void me2(){
//        System.out.println("子类方法");
//    }

    //   也可以在报错的地方  使用 Alt + 回车
    public Dog(String name, int age, String color) {
        super(name, age, color);// super()  作用是调用 父类的构造方法
        System.out.println("子类构造方法");
    }

    @Override
    public void eat(){
        System.out.println(this.name + "正在吃狗粮");
    }


    public void bark(){
        System.out.println(this.name + "在叫");
    }

//    public void eat(){
//        System.out.println(this.name + "在吃狗粮");
//    }
}

class Cat extends Animal{

    public Cat(String name,int age,String color){
        super(name,age,color); // super()  作用是调用 父类的构造方法
    }

    public void miao(){
        System.out.println(this.name + "喵喵叫");
    }

//    public void eat(){
//        System.out.println(this.name + "在吃猫粮");
//    }
}

public class Blog {
    public static void main(String[] args) {
        //向上转型    即   把子类对象给父类

        //形式一
        Dog dog = new Dog("阿泽",10,"米色");
        // 在实例化对象时   比如说 ”=“ 右边 new Dog();
        //在new 的时候  会去找构造方法，根据传入（）内的参数 ，去进行赋值和初始化

        // 执行流程
        // 1.进main 方法
        // 2.new Dog() 时 去找子类构造方法
        // 3.因为子类继承父类，要想执行子类构造方法，必须先执行父类构造方法,因此会先跳到父类的构造方法
        // 4.因为父类里有静态代码块，实例代码块，静态方法，普通方法等
        //   4.1 先执行 父类静态代码块
        //       再执行 子类静态代码块
        //             父类实例代码块  父类构造方法   子类实例代码块 子类构造方法
        //             成员方法 被调用才会起作用


        Animal animal1 = dog;


        //形式二
        Animal animal2 = new Dog("小罗",10,"白色");//向上转型
        //父类引用          子类对象

        animal2.eat();
        //方法的重写
        //1.方法名相同
        //2.方法的参数列表相同(个数,顺序,类型)
        //3.方法的返回值相同

        //总结：
        //1.静态方法不能被重写
        //2.被private修饰的方法不能被重写
        //3.被final修饰的方法[密封方法]不能被重写
        //4.如果方法被重写，那么子类的访问权限一定要 大于 等于父类的访问权限

        //方法重载是一个类的多态性表现，而方法重写是子类与父类的一种多态性表现




        //子类没有自己的eat方法时，只输出了父类(Animal类)的eat方法  xxx正在吃
        //但如果子类(Dog类)   有自己的eat方法(方法的重写)，    那此时的 animal2.eat();将输出子类 重写的eat方法 的内容
        //                                                                  即输出 xxx正在吃狗粮
        //此过程为动态绑定

        //动态绑定的前提
        //1.方法重写
        //2.发生向上转型
        //
        // 即：
        //
        // 1.父类引用  引用子类对象 [向上转型]
        // 2.通过父类引用 调用 重写的方法


        //静态绑定 --》在编译的时候 就确定调用哪个方法了?
        //例：add(int,int){.....}
        //   add(int,int,int){......}
        //
        //   写add(1,2,3)时就知道要调用哪个方法




//        animal2.bark();
        //此语句会报错 因为 父类(Animal)里没有 bark方法

    }
}
